﻿#include "WorkerWidget.h"
#include "ui_WorkerWidget.h"

#include <QDebug>

#include "GlobalDefine.h"

#include "../lib/env.h"
#include "../lib/function.h"
#include "../lib/function_group.h"
#include "../lib/variable.h"
#include "../lib/variable_group.h"

class WorkerWidget::WorkerWidgetPrivate :public QObject, public AstWorker
{
public:
	QString label_name;

	void		*env;
	struct function_group_s * function_group_ptr;
	struct variable_group_s * constant_group_ptr;
	struct variable_group_s * variable_group_ptr;
	bool		input_mode; // 是否编辑/输入状态，编译成功后置false
	int			compile_error;	// 编译成功否
public:
	WorkerWidgetPrivate(QObject*parent) :QObject(parent)
	{
		input_mode = false;
		compile_error = 0;

		function_group_ptr = nullptr;
		constant_group_ptr = nullptr;

		env = nullptr;
		env_create(&env);

		// 初始化变量
		variable_group_ptr = nullptr;
		//int r = variable_group_create(&variable_group_ptr);
		//env_set_variable_group(env, variable_group_ptr);
	}
	~WorkerWidgetPrivate()
	{
		if (variable_group_ptr) {
			variable_group_free(variable_group_ptr);
		}
		if (env)
			env_free(env);
	}
	void initVariableToEnv()
	{
		int r = variable_group_create(&variable_group_ptr);
		env_set_variable_group(env, variable_group_ptr);
	}
	void setFunctions(void*funcs)
	{
		function_group_ptr = (struct function_group_s*)funcs;
		env_set_function_group(env, function_group_ptr, 0);
	}
	void setConstant(void*con)
	{
		constant_group_ptr = (struct variable_group_s*)con;
		env_set_constant_group(env, constant_group_ptr);
	}
	int getEnvError(QString*msg)
	{
		if (!env) {
			if (msg) *msg = QStringLiteral("没有脚本实例");
			return -1;
		}
		int r = env_get_errorcode(env);
		if (r && msg) {
			*msg = env_get_errorstring(env);
		}
		return r;
	}

	int getEnvLocation(env_errorlocation*loc)
	{
		return env_get_errorlocation(env, loc);
	}

	virtual int type() override
	{
		return AstScene::SCENE_WORKER;
	}
	virtual QString typeName() override
	{
		return "WorkerScene";
	}
	virtual QString label()
	{
		return label_name;
	}
	virtual void setLabel(const QString&s)
	{
		label_name = s;
	}
	virtual QWidget* widget() override
	{
		return qobject_cast<QWidget*>(parent());
	}
	//virtual void setEnvFunctions(void*funcs)
	//{}
	virtual int parseString(const QString&s) override
	{
		if (!env)
			return -1;

		env_clean(env);
		qDebug() << "env_clean";
		initVariableToEnv();
		qDebug() << "initVariableToEnv";

		char*str = "s=OpenScene(1,'in-1');n=TextInSceneRowCount(s);\n" "x=1;";

		//int r = env_parse_string(env, str);
		int r = env_parse_string(env, s.toUtf8().toStdString().c_str());

		return r;
	}
	virtual int run() override
	{
		if (!env)
			return -1;

		variable_group_clean(variable_group_ptr);
		return env_exec(env);
	}
	virtual void onOpening() override
	{}
	virtual void onClosing() override
	{}
};

WorkerWidget::WorkerWidget(QWidget *parent)
	: QWidget(parent),private_ptr(new WorkerWidgetPrivate(this))
{
	ui = new Ui::WorkerWidget();
	ui->setupUi(this);
}

WorkerWidget::~WorkerWidget()
{
	delete ui;
}

AstWorker* WorkerWidget::operator()()
{
	return dynamic_cast<AstWorker*>(private_ptr);
}

void WorkerWidget::setEnvFunctions(void*funcs)
{
	private_ptr->setFunctions(funcs);
}
void WorkerWidget::setEnvConstants(void*con)
{
	private_ptr->setConstant(con);
}

void WorkerWidget::on_btn_compile_clicked()
{
	QString msg;
	if (private_ptr->input_mode) {
		int r = private_ptr->parseString(ui->edt_script->toPlainText());
		if (r) {
			int err = private_ptr->getEnvError(&msg);
			env_errorlocation errloc = { 0 };
			int res = private_ptr->getEnvLocation(&errloc);
			msg = QStringLiteral("error(%1)[%3:%4 - %5:%6]：%2").arg(err).arg(msg)
				.arg(errloc.first_line).arg(errloc.first_column)
				.arg(errloc.last_line).arg(errloc.last_column);
		}
		else {
			private_ptr->input_mode = false;
			msg = QStringLiteral("编译成功！");
		}
		private_ptr->compile_error = r;
		ui->lbl_msg->setText(msg);
	}
}
void WorkerWidget::on_btn_exec_clicked()
{
	on_btn_compile_clicked();

	QString msg;
	if (0 == private_ptr->compile_error) {
		int r = private_ptr->run();
		if (r) {
			int err = private_ptr->getEnvError(&msg);
			msg = QStringLiteral("运行错误(%1)：%2").arg(err).arg(msg);
		}
		else {
			msg = "OK";
		}
		ui->lbl_msg->setText(msg);
	}

	//private_ptr->run();
}
void WorkerWidget::on_edt_script_modificationChanged(bool b)
{
	//qDebug() << "on_edt_script_modificationChanged:" << b;
}
void WorkerWidget::on_edt_script_textChanged()
{
	//qDebug() << "on_edt_script_textChanged";
	ui->lbl_msg->setText(QStringLiteral("文本编辑中"));
	private_ptr->input_mode = true;
}
